/*
 * Copyright (c) 2011, TUgether, TU Braunschweig
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @author Mohamed Karray <mohamed.karray@gmx.de>
 * 		   Mark Stein <mark.stein.ms@gmail.com>
 *
 */

package de.tu_bs.tugether.liferayunit.liferayElements.portlets;

import java.io.*;
import java.util.*;

import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.*;

import de.tu_bs.tugether.liferayunit.exceptions.*;
import de.tu_bs.tugether.liferayunit.liferayElements.*;
import de.tu_bs.tugether.liferayunit.liferayPages.*;
import de.tu_bs.tugether.liferayunit.liferayPages.controlPanel.EditRolePermissionPage;

public class Portlet extends LiferayElement {

	private static final String XPATH_KEY_MINIMIZE = "minimize";
	private static final String XPATH_KEY_MAXIMIZE = "maximize";
	private static final String XPATH_KEY_CLOSE = "close";
	private static final String XPATH_KEY_BACK = "back";
	private static final String XPATH_KEY_TITLE = "title";
	private static final String XPATH_KEY_IS_MINIMIZED = "isMinimized";
	private static final String XPATH_KEY_RENAME_INPUT = "rename.input";
	private static final String XPATH_KEY_RENAME_SAVE_BUTTON = "rename.input.save";
	private static final String XPATH_KEY_RENAME_CANCEL_BUTTON = "rename.input.cancel";

	private HtmlAnchor minimizeAnchor;
	private HtmlAnchor maximizeAnchor;
	private HtmlAnchor closeAnchor;
	private HtmlAnchor backAnchor;
	private HtmlElement title;
	private String plid;

	enum XpathKeys {
		PORTLET_CONFIGURATION_ANCHOR, PORTLET_ELEMENT, PORTLET_CONFIGURATION_PERMISSION_ANCHOR,
		PERMISSION_FORM, PERMISSION_SEARCH_INPUT, PERMISSION_SEARCH_BUTTON, PERMISSION_CHECKBOX, SAVE_BUTTON, PORTLET_CONFIGURATION_ICON,
		PORTLET_OPTIONS;
	}

	public Portlet(HtmlElement htmlElement, LiferayPage lfrPage) throws IOException, LiferayElementNotFoundException {
		super(htmlElement, lfrPage);
	}

	protected void initialize() throws LiferayElementNotFoundException {
		try {
			minimizeAnchor = getFirstByXPathKey(XPATH_KEY_MINIMIZE);
		} catch (LiferayUnitException e) {
			minimizeAnchor = null;
		}
		try {
			maximizeAnchor = getFirstByXPathKey(XPATH_KEY_MAXIMIZE);
		} catch (LiferayUnitException e) {
			maximizeAnchor = null;
		}
		try {
			closeAnchor = getFirstByXPathKey(XPATH_KEY_CLOSE);
		} catch (LiferayUnitException e) {
			closeAnchor = null;
		}
		try {
			title = getFirstByXPathKey(XPATH_KEY_TITLE);
		} catch (LiferayUnitException e) {
			title = null;
		}
		try {
			backAnchor = getFirstByXPathKey(XPATH_KEY_BACK);
		} catch (LiferayUnitException e) {
			backAnchor = null;
		}
		try {
			HtmlElement portletElement = getFirstByXPathKey(XpathKeys.PORTLET_ELEMENT);
			plid = portletElement.getAttribute("id").replace("portlet_", "");
			logger.debug("plid: " + plid);
		} catch (LiferayPropertyKeyNotFoundException e) {
			logger.warn("portlet plid is't initializied");
		}

	}

	public boolean isMinimized() throws LiferayUnitException {
		return super.findElementWithXPathKey(XPATH_KEY_IS_MINIMIZED);
	}

	public boolean goBack() throws Exception {
		if (this.backAnchor != null) {
			HtmlPage page = this.backAnchor.click();
			this.getLiferayPage().setPage(page);
			this.getLiferayPage().initialize();
			return true;
		}
		return false;
	}

	public boolean minimize() throws Exception {

		logger.debug("Minimize Portlet: " + this.getTitle());
		if (this.getMinimizeAnchor() == null) {
			logger.error("minimize Icon not found in Portlet " + this.getTitle());
			throw new LiferayElementNotFoundException("Minimize Icon not found in Portlet " + this.getTitle());
		}
		this.getMinimizeAnchor().click();
		return isMinimized();
	}

	public <T extends Portlet> MaximizedPortletPage<T> maximize() throws Exception {
		logger.debug("Maximize Portlet: " + this.getTitle());
		if (this.getMaximizeAnchor() == null) {
			logger.error("Maximize Icon not found in Portlet " + this.getTitle());
			throw new LiferayElementNotFoundException("Maximize Icon not found in Portlet " + this.getTitle());
		}
		HtmlPage page = this.getMaximizeAnchor().click();
		MaximizedPortletPage<T> mp = new MaximizedPortletPage<T>(page);
		this.setLiferayPage(mp);
		return mp;
	}

	public void close() throws Exception {
		close(true);
	}

	public void close(final boolean confirmDialog) throws Exception {
		String confirm = confirmDialog ? "best?tigen" : "abbrechen";
		logger.debug("Im Portlet '" + this.getTitle() + "' klicke auf Portlet schliessen und Vorgang " + confirm);
		if (this.getCloseAnchor() == null) {
			logger.error("Close Icon im Portlet " + this.getTitle() + " wurde nicht gefunden!");
			throw new LiferayElementNotFoundException("Close Icon not found in Portlet " + this.getTitle());
		}
		this.getLiferayPage().getWebClient().setConfirmHandler(new ConfirmHandler() {

			@Override
			public boolean handleConfirm(Page arg0, String arg1) {
				return confirmDialog;
			}
		});
		this.getCloseAnchor().click();
		this.getLiferayPage().getWebClient().waitForBackgroundJavaScript(2000);
		this.getLiferayPage().initializePortletList();
	}

	public void rename(String newTitle) throws Exception {
		rename(newTitle, true);
	}

	public void rename(String newTitle, boolean saveModification) throws Exception {
		this.title.mouseMove();
		Thread.sleep(5000);
		HtmlPage pageAfterClick = null;
		while (pageAfterClick == null) {
			try {
				pageAfterClick = title.click();
				Thread.sleep(5000);
			} catch (Exception e) {
				System.out.print(".");
			}
		}
		HtmlTextInput input = this.<HtmlTextInput> getFirstByXPathKey(XPATH_KEY_RENAME_INPUT);
		HtmlButton cancel = this.<HtmlButton> getFirstByXPathKey(XPATH_KEY_RENAME_CANCEL_BUTTON);
		HtmlButton save = this.<HtmlButton> getFirstByXPathKey(XPATH_KEY_RENAME_SAVE_BUTTON);
		input.setValueAttribute(newTitle);
		if (saveModification) {
			save.click();
			this.getLiferayPage().initializePortletList();
		} else
			cancel.click();

	}

	private HtmlElement getMinimizeAnchor() {
		return minimizeAnchor;
	}

	private HtmlElement getMaximizeAnchor() {
		return maximizeAnchor;
	}

	private HtmlElement getCloseAnchor() {
		return closeAnchor;
	}

	public String getTitle() {
		if (title != null)
			return title.asText();
		return null;
	}

	public String toString() {
		String result = "Portlet ";
		if (title != null) {
			result += " with title: " + title.asText();
		}
		return result + " is an " + super.toString();

	}

	public void removeAllAuthorization(String role) throws Exception {
		logger.debug("Portlet.removeAllAuthorization(...) role: " + role);
		HtmlPage page = goToPermissionsPage(role);

		for (PermissionType pType : PermissionType.values()) {
			HtmlCheckBoxInput check = page.getFirstByXPath(getXPath(XpathKeys.PERMISSION_CHECKBOX.name(), pType.name()));
			if (check != null && check.isChecked()) {
				check.click();
			}
		}

		HtmlSubmitInput save = page.getFirstByXPath(getXPath(XpathKeys.SAVE_BUTTON.name()));
		try {
			save.click();
		} catch (NullPointerException e) {
		}

	}

	 private HtmlPage goToPermissionsPage(String permission) throws Exception {

	    logger.debug("go to permissions page and search for permission [" + permission + "]");
	    HtmlPage page = goToEditRolePermissionPage().getPage();

	    logger.debug("----\n" + page.asXml() + "\n-------");

	    getLiferayPage().getWebClient().waitForBackgroundJavaScript(3000);

	    HtmlForm form = page.getFirstByXPath(getXPath(XpathKeys.PERMISSION_FORM.name()));
	    HtmlTextInput input = form.getFirstByXPath(getXPath(XpathKeys.PERMISSION_SEARCH_INPUT.name()));
	    HtmlSubmitInput search = form.getFirstByXPath(getXPath(XpathKeys.PERMISSION_SEARCH_BUTTON.name()));
	    input.setValueAttribute(permission);

	    page.getWebClient().setJavaScriptEnabled(false);
	    page = search.click();
	    page.getWebClient().setJavaScriptEnabled(true);
	    return page;
	  }

	public EditRolePermissionPage goToEditRolePermissionPage() throws Exception {
	  HtmlAnchor a = (HtmlAnchor) getFirstByXPathKey(XpathKeys.PORTLET_OPTIONS);
		HtmlPage h_page = a.click();
		a = h_page.getFirstByXPath(getXPath(XpathKeys.PORTLET_CONFIGURATION_ANCHOR.name(), plid));
		String hrefAttribute = a.getHrefAttribute();
		WebClient wc = h_page.getWebClient();
		wc.setThrowExceptionOnFailingStatusCode(false);
		h_page = wc.getPage(hrefAttribute);
		a = h_page.getFirstByXPath(getXPath(XpathKeys.PORTLET_CONFIGURATION_PERMISSION_ANCHOR.name()));
		h_page = a.click();
		return new EditRolePermissionPage(h_page);

	}


	private HtmlElement getFirstByXPathKey(XpathKeys xpath, String... values) throws LiferayPropertyKeyNotFoundException,
	        LiferayElementNotFoundException {
		logger.debug("Get Element: " + xpath.name() + " with values " + Arrays.toString(values));
		return getFirstByXPathKey(xpath.name(), values);
	}

}


